package com.hlkj.pay.util;

import java.nio.charset.StandardCharsets;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.hutool.crypto.asymmetric.SM2;

/**
 * 国密SM2算法工具类
 *
 * @description:
 * @since:
 */
public class SM2Utils {

    private static Logger logger = LoggerFactory.getLogger(SM2Utils.class);

    private SM2Utils() {
    }

    public static String sign(String plainText, String privateKeyStr) {
        SM2 sm2 = new SM2(privateKeyStr, null);
        byte[] data = plainText.getBytes(StandardCharsets.UTF_8);
        return Base64.getEncoder().encodeToString(sm2.sign(data, null));
    }

    public static boolean verify(String plainText, String signText, X509Certificate certificate) {
        Objects.requireNonNull(plainText, "plainText required");
        Objects.requireNonNull(signText, "signText required");
        return verify(plainText.getBytes(StandardCharsets.UTF_8), Base64.getDecoder().decode(signText), certificate);
    }

    private static boolean verify(byte[] plainData, byte[] signature, X509Certificate certificate) {
        try {
            Signature verifySign = Signature.getInstance(certificate.getSigAlgName());
            verifySign.initVerify(certificate);
            verifySign.update(plainData);
            return verifySign.verify(signature);
        } catch (Exception e) {
            logger.error("verify", e);
            ExceptionUtils.rethrow(e);
            return false;
        }
    }

    public static String encryptToBase64(String plainText, X509Certificate cert) {
        byte[] cipherData = encrypt(plainText.getBytes(StandardCharsets.UTF_8), cert);
        return Base64.getEncoder().encodeToString(cipherData);
    }

    private static byte[] encrypt(byte[] message, X509Certificate cert) {
        SM2 sm2 = new SM2(null, cert.getPublicKey());
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        return sm2.encrypt(message);
    }

    public static String decryptBase64Message(String cipherText, String privateKeyStr) {
        byte[] base64Data = Base64.getDecoder().decode(cipherText);
        byte[] bytes = decrypt(base64Data, privateKeyStr);
        return StringUtils.toEncodedString(bytes, StandardCharsets.UTF_8);
    }

    private static byte[] decrypt(byte[] message, String privateKeyStr) {
        SM2 sm2 = new SM2(privateKeyStr, null);
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        return sm2.decrypt(message);
    }

    public static void main(String[] args) {
        String cipherText="BEDE5aTRmguFDb62Y8HOrqQ+9n3XmHrkIF/nZxJ24owDY6JcDRw5M0uypE2WNgx+oHsNM0Lm8Ln7yKRCvasvwRt/qnZ+4YVLw2TJgOOqmMPps8WGPW5QzWXEo8dhT8gzUOW/3Eu6x7V/Z6biDbbFwiE=";
        String privateKeyStr="MIICqzCCAk+gAwIBAgIIJAkDASF2NBEwDAYIKoEcz1UBg3UFADBcMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRswGQYDVQQDDBJDRkNBIEFDUyBTTTIgT0NBMzIwHhcNMjQxMjExMDk1OTU2WhcNMjQxMjEyMDk1OTU2WjBsMQswCQYDVQQGEwJDTjEXMBUGA1UECgwOQ0ZDQSBTTTIgT0NBMzIxEDAOBgNVBAsMB2hlbGlwYXkxDjAMBgNVBAsMBVNjZW5lMSIwIAYDVQQDDBkwNTFA5LyY6L6+QFpDMTgwODY4NTYzMEAxMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEmsC6/4Cmct6n41Yzr4fNgkrCaa4MLmShCMw0g2SaWA3ByNvRxJo/EE2h+o0/YSMoSnq0E27xGHKqvxzdu7mf7KOB6DCB5TAfBgNVHSMEGDAWgBS5pzafEdeEyGT5bHTYKzQwyDGuDDAJBgNVHRMEAjAAMEgGA1UdIARBMD8wPQYIYIEchu8qAQQwMTAvBggrBgEFBQcCARYjaHR0cDovL3d3dy5jZmNhLmNvbS5jbi91cy91cy0xNC5odG0wHwYIYIEchu8qCQEEEwwRQzE4MDg2ODU2MzDkvJjovr4wDgYDVR0PAQH/BAQDAgbAMB0GA1UdDgQWBBR23RQ5XjnpKheMMKsVbbdWdDxxnzAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwDAYIKoEcz1UBg3UFAANIADBFAiBgicRw0SQpA/z85+i7+1Djy4a3BkvnPr2wh8unhmrCSgIhAJwzhgw7E5GRDe5w9OnyiUkhkWNTo8dWILu0vO5sa16d";
        System.out.println(decryptBase64Message(cipherText,privateKeyStr));
    }
}